﻿using System;
using System.Collections.Generic;
using System.Linq;

using Fuse8.DomainFramework.Domain;
using Fuse8.DomainFramework.CacheService;
using Fuse8.DomainFramework.Common;
using Fuse8.DomainFramework.Common.Locator;

namespace Fuse8.DomainFramework.DataAccess.XmlDatabase
{
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <typeparam name="TKey"></typeparam>
    public class XmlEntityDataRepository<TEntity, TKey> : BaseEntityDataRepository<TEntity, TKey, TEntity>
        where TEntity : class, IEntityObject<TKey>, new()
        where TKey : IComparable<TKey>, IEquatable<TKey> 
    {
        #region Field

        private XmlFileDB<TEntity, TKey> _database;

        #endregion

        #region Property

        /// <summary>
        /// 
        /// </summary>
        protected XmlFileDB<TEntity, TKey> Database
        {
            get
            {
                if (_database == null)
                {
                    if (!DependencyServiceLocator.Current.IsDefaultServiceRegistered<XmlFileDB<TEntity, TKey>>())
                    {
                        DependencyServiceLocator.Current.SetDefaultService<XmlFileDB<TEntity, TKey>>(new DefaultXmlFileDB<TEntity, TKey>());
                    }

                    _database = DependencyServiceLocator.Current.GetInstance<XmlFileDB<TEntity, TKey>>();
                }

                return _database;
            }
        }

        #endregion

        #region Constructor

        /// <summary>
        /// 
        /// </summary>
        public XmlEntityDataRepository()
        {
            if (!DependencyServiceLocator.Current.IsDefaultServiceRegistered<IUnitOfWorkFactory<TEntity>>())
            {
                DependencyServiceLocator.Current.SetDefaultService<IUnitOfWorkFactory<TEntity>>(
                    new StubUnitOfWorkFactory<TEntity>());
            }
        }

        #endregion

        #region BaseEntityDataRepository override

        /// <summary>
        /// 
        /// </summary>
        public override DataRepositoryCacheOptions CacheOptions
        {
            get
            {
                return DataRepositoryCacheOptions.NoCache;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="entityObject"></param>
        public override void Add(TEntity entityObject)
        {
            Guard.ArgumentNotNull(entityObject, "entityObject");

            AddToRepository(entityObject);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="entityObject"></param>
        public override void Save(TEntity entityObject)
        {
            Guard.ArgumentNotNull(entityObject, "entityObject");

            SaveToRepository(entityObject);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="entityObject"></param>
        public override void Remove(TEntity entityObject)
        {
            Guard.ArgumentNotNull(entityObject, "entityObject");

            DeleteFromRepository(entityObject);
        }
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="repositoryEntity"></param>
        protected override void AddToRepository(TEntity repositoryEntity)
        {
            Guard.ArgumentNotNull(repositoryEntity, "repositoryEntity");

            Database.Add(repositoryEntity);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="repositoryEntity"></param>
        protected override void SaveToRepository(TEntity repositoryEntity)
        {
            Guard.ArgumentNotNull(repositoryEntity, "repositoryEntity");

            Database.Save(repositoryEntity);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="repositoryEntity"></param>
        protected override void DeleteFromRepository(TEntity repositoryEntity)
        {
            Guard.ArgumentNotNull(repositoryEntity, "repositoryEntity");

            Database.Remove(repositoryEntity);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        protected override void DeleteFromRepository(TKey id)
        {
            var repositoryEntity = FindOne(id);

            if (repositoryEntity != null)
            {
                DeleteFromRepository(repositoryEntity);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        protected override IQueryable<TEntity> AsQueryable()
        {
            return Database.Repository;
        }

        #endregion        
    }
}
